#include <modules\textureModule.h>
#include <model.h>

#include "Poco\DirectoryIterator.h"
#include <Poco\File.h>
#include <Poco\Path.h>

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

using Poco::DirectoryIterator;
using Poco::File;
using Poco::Path;

textureModule::textureModule(vec2i _tile_res, vec2i _levels_interval, int _level0_offset, string _datasourcedir) : dataModule() {
  tile_res = _tile_res;
  levels_interval = _levels_interval;
  datasourcedir = _datasourcedir;
  level0_offset = _level0_offset;
}

bool
textureModule::post(model * _model) {

  mysqlDatabase db = _model->getDB();

  // check/create texture tables for all levels
  stringstream query;

  bool res = true;
  for (int level = levels_interval[0]; level <= levels_interval[1]; level++) {
    query.str("");
    query << TEXTURE_TABLE_BASE_NAME << "_" << level;
    if (!tableExists(&db, query.str())) {
      res = res && createTable(&db, query.str());
      if (!res) return false;
    }
  }

  // use the data source directory to fulfil the database
  // the directory structure is:
  //
  //  L::CM::C::RM::R
  //  level, column multiplier, column, row multiplier, row.png(jpg)
  //
  Path basedir(datasourcedir);
  Path currdir(basedir);

  DirectoryIterator L;
  DirectoryIterator CM;
  DirectoryIterator C;
  DirectoryIterator RM;
  DirectoryIterator R;
  DirectoryIterator end;

  L = basedir;
  while (L != end) {
    currdir.pushDirectory(L.name());
    CM = currdir;
    int level = atoi(L.name().c_str()) - level0_offset;

    while (CM != end) {
      currdir.pushDirectory(CM.name());
      int col_mult = 1024 * atoi(CM.name().c_str());
      C = currdir;

      while (C != end) {
        currdir.pushDirectory(C.name());
        int col = atoi(C.name().c_str());
        col += col_mult;
        RM = currdir;

        while (RM != end) {
          currdir.pushDirectory(RM.name());
          int row_mult = 1024 * atoi(RM.name().c_str());
          R = currdir;

          while (R != end) {
            int row = atoi(R.name().c_str());
            row += row_mult;

            File file(R.path());
            fstream input_stream(file.path().c_str(), fstream::in | fstream::binary);

            stringstream query;
            query << "INSERT INTO texture_tiles_" << level
                  << " (x, y, data) VALUES ("
                  << col << "," << row << "," << "?)";

            try {
              std::auto_ptr<sql::PreparedStatement> 
                prepstmt(db.prepareQuery(query.str()));
              prepstmt->setBlob(1, &input_stream);
              prepstmt->execute();
              prepstmt->close();
            }
            catch (SQLException &e) {
              cerr << "ERROR: " << e.what();
              cerr << " (MySQL error code: " << e.getErrorCode();
              cerr << ", SQLState: " << e.getSQLState() << ")" << endl;
            }

            input_stream.close();

            R++;
          }

          currdir.popDirectory();
          RM++;
        }

        currdir.popDirectory();
        C++;
      }
      
      currdir.popDirectory();
      CM++;
    }

    std::cout << level << endl;

    currdir.popDirectory();
    L++;
  }
      
  std::cout << "done " << endl;

  return false;
}